package glkjni;


import java.io.File;

import org.brickshadow.jglk.GlkEventType;
import org.brickshadow.jglk.GlkFileMode;
import org.brickshadow.jglk.GlkFileUsage;
import org.brickshadow.jglk.GlkGestalt;
import org.brickshadow.jglk.GlkStyle;
import org.brickshadow.jglk.GlkStyleHint;
import org.brickshadow.jglk.GlkWinMethod;


/**
 * General Glk API methods.
 * <p>
 * See the {@link glkjni glkjni package} for general implementation
 * notes.
 */
public interface Glk {

    /**
     * Forwarded from {@code glk_gestalt_ext}.
     * <p>
     * Returns information about support for a certain capability.
     * 
     * @param sel
     *           The capability that you are requesting information about.
     *           It may be one of the constants in {@link GlkGestalt}.<p>
     * @param val
     *           More specific information about the requested
     *           capability.<p>
     * @param arr
     *           If non-null, it can be used to return additional
     *           information.<p>
     * @return
     *           The status of the requested capability.
     */
    int gestalt(int sel, int val, int[] arr);

    /**
     * Forwarded from {@code glk_fileref_create_by_name}.
     * <p>
     * Returns a {@code File} representing the name that should be used,
     * or {@code null} to indicate failure.
     * 
     * @param filename
     *           The name requested by the program.<p>
     * @param usage
     *           The purpose of the file; it can be interpreted using the
     *           methods in {@link GlkFileUsage}.<p>
     * @return
     *           A {@code File} object representing the name to be used,
     *           or {@code null} to indicate failure.
     */
    File namedFile(String filename, int usage);

    /**
     * Forwarded from {@code glk_fileref_create_by_prompt}.
     * <p>
     * Requests a filename from the user.
     * 
     * @param usage
     *           The purpose of the file; it can be interpreted using the
     *           methods in {@link GlkFileUsage}.<p>
     * @param fmode
     *           One of the constants in {@link GlkFileMode}.<p>
     * @return
     *           A {@code File} representing the name entered by the user,
     *           or {@code null} to indicate failure.
     */
    File promptFile(int usage, int fmode);

    /**
     * Forwarded from {@code glk_window_open}.
     * <p>
     * Creates a new Glk window.
     * 
     * @param splitwin
     *           The {@code GlkWindow} object for the window that is being
     *           split, or {@code null}.<p>
     * @param method
     *           The requested direction and division for the split; it
     *           can be interpreted using the methods in
     *           {@link GlkWinMethod}.<p>
     * @param size
     *           The requested size for the new window. Its meaning
     *           depends on the values of {@code method} and
     *           {@code wintype}:
     *           <ul>
     *           <li>For {@code GlkWinMethod.Proportional}, the size is
     *               a percentage</li>
     *           <li>For {@code GlkWinMethod.Fixed}, the size is a value in
     *               the measurement system of the split window (lines of
     *               text for text windows, pixels for graphics windows). It
     *               may be greater than the split window's actual size.
     *           </ul>
     *           In any case, {@code size} will never be negative.<p>
     * @param wintype
     *           The type of the window. It will be one of the constants
     *           {@code GlkWinType#TextBuffer}, {@code GlkWinType#TextGrid},
     *           or {@code GlkWinType#Graphics}.<p>
     * @param id
     *           Not a rock value, but a unique id generated by GlkJNI for
     *           the new window.<p>
     * @param wins
     *           Used to return references to newly-created
     *           {@code GlkWindows} back to GlkJNI. {@code win[0]} will
     *           refer to the new window, and if necessary {@code win[1]}
     *           will refer to the newly-created pair window.<p>
     */
    void windowOpen(GlkWindow splitwin, int method, int size, int wintype,
            int id, GlkWindow[] wins);

    /**
     * Forwarded from {@code glk_window_close}.
     * <p>
     * Closes a window.
     * 
     * @param win
     *           The window to close.
     */
    void windowClose(GlkWindow win);

    /**
     * Forwarded from {@code glk_stylehint_set}.
     * <p>
     * Requests that a style hint be set for windows of a certain type.
     * 
     * @param wintype
     *           The type of the window. It will be one of the constants
     *           {@code GlkWinType#AllTypes}, {@code GlkWinType#TextGrid},
     *           or {@code GlkWinType#TextBuffer}.<p>
     * @param styl
     *           One of the constants in {@link GlkStyle}.<p>
     * @param hint
     * 			 One of the constants in {@link GlkStyleHint}.<p>
     * @param val
     *           A value appropriate for the {@code hint}.<p>
     */
    void setStyleHint(int wintype, int styl, int hint, int val);

    /**
     * Forwarded from {@code glk_stylehint_clear}.
     * <p>
     * Requests that a style hint be cleared for windows of a certain
     * type.
     * 
     * @param wintype
     *           The type of the window. It will be one of the constants
     *           {@code GlkWinType#AllTypes}, {@code GlkWinType#TextGrid},
     *           or {@code GlkWinType#TextBuffer}.<p>
     * @param styl
     *           One of the constants in {@link GlkStyle}.<p>
     * @param hint
     * 			 One of the constants in {@link GlkStyleHint}.<p>
     */
    void clearStyleHint(int wintype, int styl, int hint);

    /**
     * Forwarded from {@code glk_schannel_create}.
     * <p>
     * Creates a new {@link GlkSChannel}.
     * 
     * @return a new {@code GlkSChannel}.
     */
    GlkSChannel createChannel();

    /**
     * Forwarded from {@code glk_schannel_destroy}.
     * <p>
     * Destroys a sound channel.
     * 
     * @param schan
     *           The channel to destroy.
     */
    void destroyChannel(GlkSChannel schan);

    /**
     * Forwarded from {@code glk_sound_load_hint}.
     * <p>
     * Requests that a sound be preloaded (if {@code flag} is
     * {@code true}) or unloaded.
     * 
     * @param num
     *           The number of the affected sound resource.<p>
     * @param flag
     *           True to request preloading; false to request
     *           unloading.<p>
     */
    void setSoundLoadHint(int num, boolean flag);

    /**
     * Forwarded from {@code glk_image_get_info}.
     * <p>
     * Gets the size of an image.
     * 
     * @param num
     *           The number of an image resource.<p>
     * @param dim
     *           Used to return the size of the image. {@code dim[0]}
     *           will be set to the width, and {@code dim[1]} to the
     *           height.<p>
     * @return
     *           True if the image information could be determined.
     */
    boolean getImageInfo(int num, int[] dim);

    /**
     * Forwarded from {@code glk_request_timer_events} (when called
     * with a non-zero value).
     * <p>
     * Requests timer events at a certain interval. It may be called
     * several times, with varying values for {@code millisecs},
     * without an intervening call to {@link #cancelTimer()}.
     * 
     * @param millisecs
     *           The (positive, non-zero) interval between timer
     *           events.<p>
     */
    void requestTimer(int millisecs);

    /**
     * Forwarded from {@code glk_request_timer_events} (when called with
     * zero).
     * <p>
     * Cancel the sending of timer events.
     */
    void cancelTimer();

    /**
     * Forwarded from {@code glk_select}.
     * <p>
     * Waits until an event is available, and then fills in the
     * {@code event} array with the details of the event.
     * <ul>
     * <li><b>{@code event[0]}</b> - one of the constants in
     *     {@link GlkEventType}.</li>
     * <li><b>{@code event[1]}</b> - if non-zero, it should be a window
     *     id (the value that was passed to
     *     {@link #windowOpen(GlkWindow, int, int, int, int,
     *     GlkWindow[])}).</li>
     * <li><b>{@code event[2]}</b> - an appropriate value for the type of
     *     event.</li>
     * <li><b>{@code event[3]}</b> - an appropriate secondary value for the
     *     type of event.</li>
     * </ul>
     * @param event
     *           The details of the event.<p>
     */
    void select(int[] event);

    /**
     * Forwarded from {@code glk_select_poll}.
     * <p>
     * Checks for events of type {@code GlkEventType#Arrange},
     * {@code GlkEventType#Timer}, and {@code GlkEventType#SoundNotify}.
     * If one is available, {@code event} is filled in with the details
     * of the event, as by {@link #select(int[])}. If not,
     * {@code event[0]} is set to {@link GlkEventType#None}.
     * 
     * @param event
     *           The details of the event.<p>
     */
    void poll(int[] event);

    /**
     * Forwarded from {@code glk_exit}.
     * <p>
     * Exits the program.
     * <p>
     */
    void exit();
}
